"""
文档切片API路由
"""
import os
import json
import uuid
from typing import Optional, List
from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
import zipfile

from core.database import get_db
from api.auth import get_current_user
from core.auth import generate_slice_id
from models.database import User, ParseTask, SliceTask, SliceChunk
from models.schemas import (
    SliceTaskCreate, SliceTaskResponse, SliceCompleteResponse, 
    SliceOptions, SliceStrategy, BaseResponse, TaskStatus
)
from core.config import get_settings
from core.logger import api_logger, get_task_logger, log_api_call
from services.slice_service import SliceService

router = APIRouter()
settings = get_settings()


@router.post("/create", response_model=BaseResponse)
@log_api_call
async def create_slice_task(
    task_data: SliceTaskCreate,
    background_tasks: BackgroundTasks,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """创建切片任务"""
    try:
        # 验证解析任务
        parse_task = db.query(ParseTask).filter(
            ParseTask.id == task_data.parse_task_id
        ).first()
        
        if not parse_task:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Parse task not found"
            )
        
        # 检查权限
        if current_user.role != "admin" and parse_task.user_id != current_user.id:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Access denied"
            )
        
        # 检查解析任务是否完成
        if parse_task.status != TaskStatus.COMPLETED:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Parse task must be completed before slicing"
            )
        
        # 生成切片ID
        slice_id = generate_slice_id()
        
        # 创建切片任务
        slice_task = SliceTask(
            slice_id=slice_id,
            parse_task_id=task_data.parse_task_id,
            status=TaskStatus.PENDING,
            strategy=task_data.options.strategy,
            chunk_size=task_data.options.chunk_size,
            overlap=task_data.options.overlap,
            min_chunk_size=task_data.options.min_chunk_size
        )
        
        db.add(slice_task)
        db.commit()
        db.refresh(slice_task)
        
        # 创建任务日志记录器
        task_logger = get_task_logger(slice_id)
        task_logger.info("Slice task created", {
            "parse_task_id": task_data.parse_task_id,
            "strategy": task_data.options.strategy.value,
            "chunk_size": task_data.options.chunk_size
        })
        
        # 添加后台任务
        background_tasks.add_task(
            process_slice_task_async,
            slice_id,
            task_data.parse_task_id,
            task_data.options.dict(),
            current_user.id
        )
        
        api_logger.log_task_event("slicing", "slice_task_created", {
            "slice_id": slice_id,
            "parse_task_id": task_data.parse_task_id,
            "user_id": current_user.id
        })
        
        return BaseResponse(
            success=True,
            message="Slice task created successfully",
            data={"slice_id": slice_id}
        )
        
    except HTTPException:
        raise
    except Exception as e:
        api_logger.log_error(e, {"endpoint": "/slicing/create"})
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Internal server error"
        )


@router.get("/status/{slice_id}", response_model=SliceTaskResponse)
@log_api_call
async def get_slice_task_status(
    slice_id: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取切片任务状态"""
    try:
        slice_task = db.query(SliceTask).filter(SliceTask.slice_id == slice_id).first()
        
        if not slice_task:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Slice task not found"
            )
        
        # 检查权限
        parse_task = db.query(ParseTask).filter(ParseTask.id == slice_task.parse_task_id).first()
        if not parse_task or (current_user.role != "admin" and parse_task.user_id != current_user.id):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Access denied"
            )
        
        return SliceTaskResponse.from_orm(slice_task)
        
    except HTTPException:
        raise
    except Exception as e:
        api_logger.log_error(e, {"endpoint": "/slicing/status", "slice_id": slice_id})
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Internal server error"
        )


@router.get("/result/{slice_id}", response_model=SliceCompleteResponse)
@log_api_call
async def get_slice_result(
    slice_id: str,
    page: int = 1,
    limit: int = 10,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取切片结果"""
    try:
        slice_task = db.query(SliceTask).filter(SliceTask.slice_id == slice_id).first()
        
        if not slice_task:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Slice task not found"
            )
        
        # 检查权限
        parse_task = db.query(ParseTask).filter(ParseTask.id == slice_task.parse_task_id).first()
        if not parse_task or (current_user.role != "admin" and parse_task.user_id != current_user.id):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Access denied"
            )
        
        if slice_task.status != TaskStatus.COMPLETED:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Slice task not completed"
            )
        
        # 获取切片块
        offset = (page - 1) * limit
        chunks = db.query(SliceChunk).filter(
            SliceChunk.slice_task_id == slice_task.id
        ).offset(offset).limit(limit).all()
        
        chunk_responses = []
        for chunk in chunks:
            chunk_data = {
                "id": chunk.id,
                "chunk_id": chunk.chunk_id,
                "text_content": chunk.text_content,
                "word_count": chunk.word_count,
                "page_number": chunk.page_number,
                "position_info": chunk.position_info,
                "metadata": chunk.chunk_metadata,
                "created_at": chunk.created_at
            }
            chunk_responses.append(chunk_data)
        
        return SliceCompleteResponse(
            slice_id=slice_id,
            status=slice_task.status,
            chunks=chunk_responses,
            total_chunks=slice_task.total_chunks,
            download_url=f"/api/v1/slicing/download/{slice_id}"
        )
        
    except HTTPException:
        raise
    except Exception as e:
        api_logger.log_error(e, {"endpoint": "/slicing/result", "slice_id": slice_id})
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Internal server error"
        )


@router.get("/download/{slice_id}")
@log_api_call
async def download_slice_result(
    slice_id: str,
    format: str = "json",
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """下载切片结果"""
    try:
        slice_task = db.query(SliceTask).filter(SliceTask.slice_id == slice_id).first()
        
        if not slice_task:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Slice task not found"
            )
        
        # 检查权限
        parse_task = db.query(ParseTask).filter(ParseTask.id == slice_task.parse_task_id).first()
        if not parse_task or (current_user.role != "admin" and parse_task.user_id != current_user.id):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Access denied"
            )
        
        if slice_task.status != TaskStatus.COMPLETED:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Slice task not completed"
            )
        
        if format == "json":
            # 返回JSON格式
            chunks = db.query(SliceChunk).filter(SliceChunk.slice_task_id == slice_task.id).all()
            
            result_data = {
                "slice_id": slice_id,
                "strategy": slice_task.strategy,
                "chunk_size": slice_task.chunk_size,
                "overlap": slice_task.overlap,
                "total_chunks": slice_task.total_chunks,
                "chunks": [
                    {
                        "chunk_id": chunk.chunk_id,
                        "text_content": chunk.text_content,
                        "word_count": chunk.word_count,
                        "page_number": chunk.page_number,
                        "position_info": chunk.position_info,
                        "metadata": chunk.chunk_metadata
                    }
                    for chunk in chunks
                ]
            }
            
            # 创建临时文件
            temp_file = os.path.join(settings.parsed_results_dir, f"{slice_id}_chunks.json")
            with open(temp_file, 'w', encoding='utf-8') as f:
                json.dump(result_data, f, ensure_ascii=False, indent=2)
            
            return FileResponse(
                path=temp_file,
                filename=f"slice_result_{slice_id}.json",
                media_type="application/json"
            )
        
        elif format == "txt":
            # 返回文本格式
            chunks = db.query(SliceChunk).filter(SliceChunk.slice_task_id == slice_task.id).all()
            
            temp_file = os.path.join(settings.parsed_results_dir, f"{slice_id}_chunks.txt")
            with open(temp_file, 'w', encoding='utf-8') as f:
                for i, chunk in enumerate(chunks):
                    f.write(f"=== Chunk {i+1} ===\n")
                    f.write(f"ID: {chunk.chunk_id}\n")
                    f.write(f"Word Count: {chunk.word_count}\n")
                    if chunk.page_number:
                        f.write(f"Page: {chunk.page_number}\n")
                    f.write("\n")
                    f.write(chunk.text_content)
                    f.write("\n\n" + "="*50 + "\n\n")
            
            return FileResponse(
                path=temp_file,
                filename=f"slice_result_{slice_id}.txt",
                media_type="text/plain"
            )
        
        else:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Unsupported format: {format}"
            )
        
    except HTTPException:
        raise
    except Exception as e:
        api_logger.log_error(e, {"endpoint": "/slicing/download", "slice_id": slice_id})
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Internal server error"
        )


@router.get("/list", response_model=List[SliceTaskResponse])
@log_api_call
async def get_slice_task_list(
    parse_task_id: Optional[int] = None,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取切片任务列表"""
    try:
        query = db.query(SliceTask)
        
        # 权限过滤
        if current_user.role != "admin":
            # 获取用户的所有解析任务ID
            user_parse_task_ids = db.query(ParseTask.id).filter(
                ParseTask.user_id == current_user.id
            ).all()
            user_parse_task_ids = [pt.id for pt in user_parse_task_ids]
            query = query.filter(SliceTask.parse_task_id.in_(user_parse_task_ids))
        
        # 按解析任务过滤
        if parse_task_id:
            query = query.filter(SliceTask.parse_task_id == parse_task_id)
        
        slice_tasks = query.order_by(SliceTask.created_at.desc()).all()
        
        return [SliceTaskResponse.from_orm(task) for task in slice_tasks]
        
    except Exception as e:
        api_logger.log_error(e, {"endpoint": "/slicing/list"})
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Internal server error"
        )


@router.delete("/{slice_id}", response_model=BaseResponse)
@log_api_call
async def delete_slice_task(
    slice_id: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """删除切片任务"""
    try:
        slice_task = db.query(SliceTask).filter(SliceTask.slice_id == slice_id).first()
        
        if not slice_task:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Slice task not found"
            )
        
        # 检查权限
        parse_task = db.query(ParseTask).filter(ParseTask.id == slice_task.parse_task_id).first()
        if not parse_task or (current_user.role != "admin" and parse_task.user_id != current_user.id):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Access denied"
            )
        
        # 删除相关文件
        import os
        import shutil
        
        if slice_task.result_path and os.path.exists(slice_task.result_path):
            if os.path.isdir(slice_task.result_path):
                shutil.rmtree(slice_task.result_path)
            else:
                os.remove(slice_task.result_path)
        
        # 删除切片块
        db.query(SliceChunk).filter(SliceChunk.slice_task_id == slice_task.id).delete()
        
        # 删除切片任务
        db.delete(slice_task)
        db.commit()
        
        api_logger.log_task_event("slicing", "slice_task_deleted", {
            "slice_id": slice_id,
            "user_id": current_user.id
        })
        
        return BaseResponse(
            success=True,
            message="Slice task deleted successfully"
        )
        
    except HTTPException:
        raise
    except Exception as e:
        api_logger.log_error(e, {"endpoint": "/slicing/delete", "slice_id": slice_id})
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Internal server error"
        )


async def process_slice_task_async(
    slice_id: str,
    parse_task_id: int,
    options: dict,
    user_id: int
):
    """异步处理切片任务"""
    from core.database import SessionLocal
    
    db = SessionLocal()
    task_logger = get_task_logger(slice_id)
    
    try:
        # 获取切片任务记录
        slice_task = db.query(SliceTask).filter(SliceTask.slice_id == slice_id).first()
        if not slice_task:
            task_logger.error("Slice task not found in database")
            return
        
        # 获取解析任务
        parse_task = db.query(ParseTask).filter(ParseTask.id == parse_task_id).first()
        if not parse_task:
            task_logger.error("Parse task not found in database")
            return
        
        # 更新任务状态
        slice_task.status = TaskStatus.PROCESSING
        db.commit()
        
        task_logger.info("Slice task processing started", {"parse_task_id": parse_task_id})
        
        # 创建切片服务
        slice_service = SliceService()
        
        # 执行切片
        result = await slice_service.slice_document(
            parse_task_id=parse_task_id,
            options=options,
            slice_id=slice_id,
            task_logger=task_logger,
            db=db
        )
        
        # 更新任务状态
        slice_task.status = TaskStatus.COMPLETED
        slice_task.total_chunks = len(result.get("chunks", []))
        slice_task.completed_at = db.func.now()
        slice_task.result_path = result.get("result_path")
        db.commit()
        
        # 保存切片块
        for chunk_data in result.get("chunks", []):
            chunk = SliceChunk(
                slice_task_id=slice_task.id,
                chunk_id=chunk_data.get("chunk_id"),
                text_content=chunk_data.get("text_content"),
                word_count=chunk_data.get("word_count", 0),
                page_number=chunk_data.get("page_number"),
                position_info=chunk_data.get("position_info"),
                metadata=chunk_data.get("metadata")
            )
            db.add(chunk)
        
        db.commit()
        
        task_logger.info("Slice task completed successfully", {
            "total_chunks": slice_task.total_chunks
        })
        
        api_logger.log_task_event("slicing", "slice_task_completed", {
            "slice_id": slice_id,
            "user_id": user_id,
            "total_chunks": slice_task.total_chunks
        })
        
    except Exception as e:
        # 更新任务状态
        slice_task.status = TaskStatus.FAILED
        slice_task.error_message = str(e)
        slice_task.completed_at = db.func.now()
        db.commit()
        
        task_logger.error("Slice task failed", error=e)
        api_logger.log_error(e, {"slice_id": slice_id, "endpoint": "slice_task"})
        
    finally:
        db.close()


# 导出路由器
slicing_router = router